from functools import wraps
from flask import request, jsonify, current_app
import jwt
from app.models import Student, Admin, Teacher
import re
import os
from werkzeug.utils import secure_filename

def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        if 'Authorization' in request.headers:
            token = request.headers['Authorization']
        if not token:
            return jsonify({'code': 401, 'msg': '缺少token'}), 401
        try:
            data = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
            if data.get('role') == 'admin':
                current_user = Admin.query.get(data['admin_id'])
            elif data.get('role') == 'teacher':
                current_user = Teacher.query.get(data['user_id'])
            else:
                current_user = Student.query.get(data['user_id'])
            
            if not current_user:
                return jsonify({'code': 401, 'msg': '用户不存在'}), 401
                
        except Exception as e:
            current_app.logger.error(f'Token验证失败: {e}')
            return jsonify({'code': 401, 'msg': 'token无效'}), 401
        return f(current_user, *args, **kwargs)
    return decorated

def validate_username(username):
    """验证用户名格式"""
    if not username or len(username) < 3 or len(username) > 20:
        return False, "用户名长度必须在3-20个字符之间"
    if not re.match(r'^[a-zA-Z0-9_]+$', username):
        return False, "用户名只能包含字母、数字和下划线"
    return True, ""

def validate_password(password):
    """验证密码强度"""
    if not password or len(password) < 6:
        return False, "密码长度至少6位"
    if len(password) > 50:
        return False, "密码长度不能超过50位"
    return True, ""

def validate_email(email):
    """验证邮箱格式"""
    if not email:
        return True, ""  # 邮箱可选
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if not re.match(pattern, email):
        return False, "邮箱格式不正确"
    return True, ""

def validate_phone(phone):
    """验证手机号格式"""
    if not phone:
        return True, ""  # 手机号可选
    pattern = r'^1[3-9]\d{9}$'
    if not re.match(pattern, phone):
        return False, "手机号格式不正确"
    return True, ""

def sanitize_input(text):
    """清理输入文本"""
    if not text:
        return ""
    # 移除危险字符
    text = re.sub(r'[<>"\']', '', text)
    # 移除多余空格
    text = re.sub(r'\s+', ' ', text).strip()
    return text

def allowed_file(filename):
    """检查文件类型是否允许"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in current_app.config.get('ALLOWED_EXTENSIONS', {'png', 'jpg', 'jpeg', 'gif'})

def save_uploaded_file(file, folder='certificates'):
    """保存上传的文件"""
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        # 添加时间戳避免文件名冲突
        import time
        timestamp = str(int(time.time()))
        name, ext = os.path.splitext(filename)
        filename = f"{name}_{timestamp}{ext}"
        
        upload_path = os.path.join(current_app.root_path, '..', 'static', folder)
        os.makedirs(upload_path, exist_ok=True)
        
        file_path = os.path.join(upload_path, filename)
        file.save(file_path)
        
        return f'/static/{folder}/{filename}'
    return None

def validate_honor_data(data):
    """验证荣誉数据"""
    errors = []
    
    # 必填字段验证
    required_fields = ['title', 'honor_type', 'level', 'date', 'organization']
    for field in required_fields:
        if not data.get(field):
            errors.append(f'{field}不能为空')
    
    # 字段长度验证
    if data.get('title') and len(data['title']) > 100:
        errors.append('荣誉标题不能超过100个字符')
    
    if data.get('description') and len(data['description']) > 500:
        errors.append('荣誉描述不能超过500个字符')
    
    # 日期格式验证
    if data.get('date'):
        try:
            from datetime import datetime
            datetime.strptime(data['date'], '%Y-%m-%d')
        except ValueError:
            errors.append('日期格式不正确，请使用YYYY-MM-DD格式')
    
    return errors

def log_user_action(user, action, details=""):
    """记录用户操作日志"""
    current_app.logger.info(f'用户操作 - 用户: {user.username if hasattr(user, "username") else "未知"}, 角色: {getattr(user, "__class__.__name__", "未知")}, 操作: {action}, 详情: {details}') 